<?php
/**
 * @package qBase
 * @subpackage sql
 *
 */

/**
 * The QSqlTableField represents a generic sql database type field
 * This object uses the MySql standard for definition, any other implementations should convert
 * from this to their own format
 *
 * @package qBase
 * @subpackage sql
 */
class QSqlTableField extends QObject implements QIAllowSerialize 
{
	/**
	 * The int data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeInt			= 1;
	/**
	 * The tinyint data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeTinyint		= 18;
	/**
	 * The smallint data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeSmallint		= 19;
	/**
	 * The mediumint data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeMediumint		= 20;
	/**
	 * The bigint data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeBigint		= 2;
	/**
	 * The decimal data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeDecimal		= 3;
	/**
	 * The float data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeFloat			= 4;
	/**
	 * The double data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeDouble		= 5;
	/**
	 * The bit data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeBit			= 6;
	/**
	 * The bool data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeBool			= 7;
	/**
	 * The char data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeChar			= 8;
	/**
	 * The varchar data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeVarchar		= 9;
	/**
	 * The text data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeText			= 10;
	/**
	 * The blob data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeBlob			= 11;
	/**
	 * The enum data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeEnum			= 12;
	/**
	 * The set data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeSet			= 13;
	/**
	 * The date data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeDate			= 14;
	/**
	 * The datetime data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeDatetime		= 15;
	/**
	 * The timestamp data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeTimestamp		= 16;
	/**
	 * The time data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeTime			= 17;
	/**
	 * The text data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeMediumText	= 10;
	/**
	 * The text data type as defined by mysql (other implementations should convert)
	 *
	 */
	const TypeLongText		= 21;
	/**
	 * The current timestamp value
	 *
	 */
	const CurrentTimestamp = -999999;
	/**
	 * The name of the field
	 *
	 * @var string
	 */
	public $name;
	/**
	 * The new name that the field will take on updateField
	 *
	 * @var string
	 */
	public $new_name;
	/**
	 * The type of the field as defined by the QSqlTableField type constants
	 *
	 * @var integer
	 */
	public $type;
	/**
	 * The length of the filed (only applies for chars)
	 *
	 * @var integer
	 */
	public $length;
	/**
	 * The values for "enum" or "set", only applies to them
	 *
	 * @var string
	 */
	public $values;
	/**
	 * The default value for the field. Uses strings for constant values and integer 
	 * constants for timestamp or others
	 *
	 * @var mixed
	 */
	public $default;
	/**
	 * The charset of the field (only applies to char types)
	 *
	 * @var string
	 */
	public $charset;
	/**
	 * The collation of the field (only applies to char types)
	 *
	 * @var string
	 */
	public $collation;
	/**
	 * Sets if the field is unsigned
	 *
	 * @var boolean
	 */
	public $unsigned;
	/**
	 * Sets if the field can accept null values
	 *
	 * @var boolean
	 */
	public $null;
	/**
	 * Puts an autoincrement on the field
	 *
	 * @var boolean
	 */
	public $auto_increment;
	/**
	 * The field's comments
	 *
	 * @var string
	 */
	public $comments;
	/**
	 * The table of the field
	 *
	 * @var QSqlTable
	 */
	public $table;
	
	/**
	 * The constructor of the table
	 *
	 * @param QSqlTable $table The table of the field
	 * @param string $name The name of the field
	 * @param integer $type The type of the field as defined by the QSqlTableField type constants
	 * @param string $length The length of the filed (only applies for chars)
	 * @param string $values The values for "enum" or "set", only applies to them
	 * @param mixed $default The default value for the field. Uses strings for constant values and integer constants for timestamp or others
	 * @param string $charset The charset of the field (only applies to char types)
	 * @param string $collation The collation of the field (only applies to char types)
	 * @param boolean $unsigned Sets if the field is unsigned
	 * @param boolean $null Sets if the field can accept null values
	 * @param boolean $auto_increment Puts an autoincrement on the field
	 * @param string $comments The field's comments
	 */
	public function __construct(QSqlTable $table = null, $name = null, $type = null, $length = null, $values = null, 
		$default = null, $charset = null, $collation = null, 
		$unsigned = null, $null = null, $auto_increment = null, $comments = null)
	{
		$this->table = $table;
		$this->name = $name;
		$this->type = $type;
		$this->length = $length;
		$this->values = $values;
		if (!is_null($default))
			$this->default = $default;
		$this->charset = $charset;
		$this->collation = $collation;
		$this->unsigned = $unsigned;
		$this->null = $null;
		$this->auto_increment = $auto_increment;
		$this->comments = $comments;
	}
	
	/**
	 * Gets the table of the field or null if none it's attached yet
	 *
	 * @return QSqlTable
	 */
	public function getTable()
	{
		return $this->table;
	}
	
	/**
	 * Sets the table of the field
	 *
	 * @param QSqlTable $table
	 */
	public function setTable(QSqlTable $table)
	{
		$this->table = $table;
	}
	
	/**
	 * Unsets the table pointer
	 *
	 */
	public function unsetTable()
	{
		unset($this->table);
	}
	
	/**
	 * Gets the name of the field
	 *
	 * @return string
	 */
	public function getName()
	{
		if ($this->new_name)
			return $this->new_name;
		else 
			return $this->name;
	}
	
	/**
	 * Sets the name of the field
	 * Changes only apply on the database server after calling "updateField"
	 *
	 * @param string $name
	 * @param boolean $is_new_name If is new name , then the "new_name" variable is set instead of name so that on "updateField" we will know the old name of the field
	 */
	public function setName($name, $is_new_name = true)
	{
		if ($is_new_name)
			$this->new_name = $name;
		else 
			$this->name = $name;
	}
	
	/**
	 * Gets the new name of the field (in case of a rename)
	 *
	 * @return string
	 */
	public function getNewName()
	{
		return $this->new_name;
	}
	
	/**
	 * Gets the old name of the field (in case of a rename)
	 *
	 * @return string
	 */
	public function getOldName()
	{
		return $this->name;
	}
	
	/**
	 * Gets the type of the field
	 *
	 * @return integer
	 */
	public function getType()
	{
		return $this->type;
	}
	
	/**
	 * Sets the type of the field, only use the predefined constrants
	 * Changes only apply on the database server after calling "updateField"
	 *
	 * @param integer $type
	 */
	public function setType($type)
	{
		$this->type = $type;
	}
	
	/**
	 * Gets the length of the field (only applies for char types)
	 *
	 * @return integer
	 */
	public function getLength()
	{
		return $this->length;
	}
	
	/**
	 * Sets the length of the field (only applies for char types)
	 * Changes only apply on the database server after calling "updateField"
	 *
	 * @param integer $length
	 */
	public function setLength($length)
	{
		$this->length = $length;
	}
	
	/**
	 * Gets the values of the field for "enum" and "set" data types
	 *
	 * @return string
	 */
	public function getValues()
	{
		return $this->values;
	}
	
	/**
	 * Sets the values of the field for "enum" and "set" data types
	 * The values are set the mySql way, other implementing types should parse and convert
	 * Changes only apply on the database server after calling "updateField"
	 *
	 * @param string $values
	 */
	public function setValues($values)
	{
		$this->values = $values;
	}
	
	/**
	 * Gets the default value for the field
	 *
	 * @return string
	 */
	public function getDefault()
	{
		return $this->default;
	}
	
	/**
	 * Sets the default value for the field
	 * Changes only apply on the database server after calling "updateField"
	 *
	 * @param string $default
	 */
	public function setDefault($default)
	{
		$this->default = $default;
	}
	
	/**
	 * Gets if this field has unsigned values (only applies to numeric types)
	 *
	 * @return boolean
	 */
	public function getUnsigned()
	{
		return $this->unsigned;
	}
	
	/**
	 * Sets if this field has unsigned values (only applies to numeric types)
	 * Changes only apply on the database server after calling "updateField"
	 *
	 * @param boolean $null
	 */
	public function setUnsigned($unsigned)
	{
		$this->unsigned = $unsigned;
	}
	
	/**
	 * Gets if the field can accept null values
	 *
	 * @return boolean
	 */
	public function getNull()
	{
		return $this->null;
	}
	
	/**
	 * Sets if the field can accept null values
	 * Changes only apply on the database server after calling "updateField"
	 *
	 * @param boolean $null
	 */
	public function setNull($null)
	{
		$this->null = $null;
	}
	
	/**
	 * Gets the charset of the field
	 *
	 * @return string
	 */
	public function getCharset()
	{
		return $this->charset;
	}
	
	/**
	 * Sets the charset of the field
	 * Changes only apply on the database server after calling "updateField"
	 *
	 * @param string $charset
	 */
	public function setCharset($charset)
	{
		$this->charset = $charset;
	}
	
	/**
	 * Gets the collation of the field
	 *
	 * @return string
	 */
	public function getCollation()
	{
		return $this->collation;
	}
	
	/**
	 * Sets the collation of the field
	 * Changes only apply on the database server after calling "updateField"
	 *
	 * @param string $collation
	 */
	public function setCollation($collation)
	{
		$this->collation = $collation;
	}
	
	/**
	 * Gets the autoincrement for this field
	 *
	 * @return boolean
	 */
	public function getAutoIncrement()
	{
		return $this->auto_increment;
	}
	
	/**
	 * Sets the autoincrement for the field
	 * Changes only apply on the database server after calling "updateField"
	 *
	 * @param boolean $auto_increment
	 */
	public function setAutoIncrement($auto_increment)
	{
		$this->auto_increment = $auto_increment;
	}
	
	/**
	 * Gets the comments for this field
	 *
	 * @return string
	 */
	public function getComments()
	{
		return $this->comments;
	}
	
	/**
	 * Sets the comments for this field
	 * Changes only apply on the database server after calling "updateField"
	 *
	 * @param string $comments
	 */
	public function setComments($comments)
	{
		$this->comments = $comments;
	}
	
	/**
	 * Updates the changes made to this object on the database server
	 *
	 */
	public function updateField()
	{
		$this->table->updateField($this);
		$this->renameDone();
	}
	
	/**
	 * After rename or update we need to reset the state for $new_name
	 *
	 */
	public function renameDone()
	{
		if ($this->new_name)
		{
			$this->name = $this->new_name;
			unset($this->new_name);
		}
	}
	
	public function generateSerializedCode(&$out, &$ref_bag, &$id_pos)
	{
		$n = $id_pos++;
		$ref_bag[$n] = $this;
		
		// $props = $this->__getAllProperties();
		
		$props = array(
			"table" => $this->table,
			"name" => $this->name,
			"type" => $this->type,
			"length" => $this->length,
			"values" => $this->values,
			"default" => $this->default,
			"charset" => $this->charset,
			"collation" => $this->collation,
			"unsigned" => $this->unsigned,
			"null" => $this->null,
			"auto_increment" => $this->auto_increment,
			"comments" => $this->comments
			);
		
		$out_2 = "";
		$pos = 0;
		if ($props)
		{
			// $p_str = $this->generateSerializedCodeForArray($props, $out, $ref_bag, $id_pos);
			foreach ($props as $k => $v)
			{
				if ($pos > 0)
					$out_2 .= ",";
				$out_2 .= $this->generateSerializedCodeForVar($v, $out, $ref_bag, $id_pos);
				$pos++;
			}
		}

		$out .= "\$v_{$n} = new ".$this->getClassName()."({$out_2});\n";
		
		// );\n";
		
		
		return $n;
	}
	
	public function GetIsTypeText($field_type)
	{
		switch ($field_type)
		{
			case self::TypeInt:
			case self::TypeTinyint:
			case self::TypeSmallint:
			case self::TypeMediumint:
			case self::TypeBigint:
			case self::TypeDecimal:
			case self::TypeFloat:
			case self::TypeDouble:
			case self::TypeBit:
			case self::TypeBool:
			case self::TypeEnum:
			case self::TypeSet:
			case self::TypeDate:
			case self::TypeDatetime:
			case self::TypeTimestamp:
			case self::TypeTime:
				{
					return false;
				}
			case self::TypeVarchar:
			case self::TypeChar:
			case self::TypeText:
			case self::TypeBlob:
			case self::TypeLongText:
			case self::TypeMediumText:
			case self::TypeMediumText:
			case self::TypeMediumText:
			case self::TypeMediumText:
			case self::TypeMediumText:
			case self::TypeMediumText:
			case self::TypeMediumText:
			case self::TypeMediumText:
				
				{
					return true;
				}
			default:
				{
					throw new Exception("Unknown data type");
				}
		}
	}
	
	public function isTypeText($field_type = null)
	{
		if (is_null($field_type))
			$field_type = $this->getType();
			
		return self::GetIsTypeText($field_type);
	}
	
	public function cloneField($new_name, QSqlTable $new_table = null)
	{
		$t = $new_table ? $new_table : $this->table;
		return new QSqlTableField($t, $new_name, $this->getType(), $this->getLength(), $this->getValues(), $this->getDefault(), $this->getCharset(), $this->getCollation(), $this->getUnsigned(), $this->getNull(), $this->getAutoIncrement(), $this->getComments());
	}
}

?>